home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src890906.arc / CMDPARSE.C < prev    next >
C/C++ Source or Header  |  1989-08-13  |  5KB  |  249 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  * Improved error handling by Brian Boesch of Stanford University
  4.  */
  5. #include <stdio.h>
  6. #include "global.h"
  7. #include "cmdparse.h"
  8. #include "proc.h"
  9.  
  10. struct boolcmd {
  11.     char *str;    /* Token */
  12.     int val;    /* Value */
  13. };
  14.  
  15. static struct boolcmd Boolcmds[] = {
  16.     "y",        1,    /* Synonyms for "true" */
  17.     "yes",        1,
  18.     "true",        1,
  19.     "on",        1,
  20.     "1",        1,
  21.     "set",        1,
  22.     "enable",    1,
  23.  
  24.     "n",        0,    /* Synonyms for "false" */
  25.     "no",        0,
  26.     "false",    0,
  27.     "off",        0,
  28.     "0",        0,
  29.     "clear",    0,
  30.     "disable",    0,
  31.     NULLCHAR
  32. };
  33.  
  34. int
  35. cmdparse(cmds,line,p)
  36. struct cmds cmds[];
  37. register char *line;
  38. void *p;
  39. {
  40.     struct cmds *cmdp;
  41.     char *argv[NARG],*cp;
  42.     char **pargv;
  43.     int argc,qflag,i;
  44.     struct proc *pp;
  45.  
  46.     /* Remove cr/lf */
  47.     rip(line);
  48.  
  49.     for(argc = 0;argc < NARG;argc++)
  50.         argv[argc] = NULLCHAR;
  51.  
  52.     for(argc = 0;argc < NARG;){
  53.         qflag = 0;
  54.         /* Skip leading white space */
  55.         while(*line == ' ' || *line == '\t')
  56.             line++;
  57.         if(*line == '\0')
  58.             break;
  59.         /* Check for quoted token */
  60.         if(*line == '"'){
  61.             line++;    /* Suppress quote */
  62.             qflag = 1;
  63.         }
  64.         argv[argc++] = line;    /* Beginning of token */
  65.         /* Find terminating delimiter */
  66.         if(qflag){
  67.             /* Find quote, it must be present */
  68.             if((line = strchr(line,'"')) == NULLCHAR){
  69.                 return -1;
  70.             }
  71.             *line++ = '\0';
  72.         } else {
  73.             /* Find space or tab. If not present,
  74.              * then we've already found the last
  75.              * token.
  76.              */
  77.             if((cp = strchr(line,' ')) == NULLCHAR
  78.              && (cp = strchr(line,'\t')) == NULLCHAR){
  79.                 break;
  80.             }
  81.             *cp++ = '\0';
  82.             line = cp;
  83.         }
  84.     }
  85.     if (argc < 1) {        /* empty command line */
  86.         argc = 1;
  87.         argv[0] = "";
  88.     }
  89.     /* Lines beginning with "#" are comments */
  90.     if(argv[0] == NULLCHAR || argv[0][0] == '#')
  91.         return 0;
  92.  
  93.     /* Look up command in table; prefix matches are OK */
  94.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  95.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  96.             break;
  97.     }
  98.     if(cmdp->name == NULLCHAR) {
  99.         if(cmdp->argc_errmsg != NULLCHAR) 
  100.             printf("%s\n",cmdp->argc_errmsg);
  101.         return -1;
  102.     } else {
  103.         if(argc < cmdp->argcmin) {
  104.             /* Insufficient arguments */
  105.             printf("Usage: %s\n",cmdp->argc_errmsg);
  106.             return -1;
  107.         } else {
  108.             if(cmdp->stksize == 0){
  109.                 return (*cmdp->func)(argc,argv,p);
  110.             } else {
  111.                 /* Make private copy of argv and args */
  112.                 pargv = (char **)calloc(argc,sizeof(char *));
  113.                 for(i=0;i<argc;i++)
  114.                     pargv[i] = strdup(argv[i]);
  115.                 pp = newproc(cmdp->name,cmdp->stksize,
  116.                 (void (*)())cmdp->func,argc,pargv,p);
  117.                 pwait(pp);
  118.                 return(0);
  119.             }
  120.         }
  121.     }
  122. }
  123.  
  124. /* Call a subcommand based on the first token in an already-parsed line */
  125. int
  126. subcmd(tab,argc,argv,p)
  127. struct cmds tab[];
  128. int argc;
  129. char *argv[];
  130. void *p;
  131. {
  132.     register struct cmds *cmdp;
  133.     char **pargv;
  134.     struct proc *pp;
  135.     int found = 0;
  136.     int i;
  137.  
  138.     /* Strip off first token and pass rest of line to subcommand */
  139.     if (argc < 2) {
  140.         if (argc < 1)
  141.             printf("SUBCMD - Don't know what to do?\n");
  142.         else
  143.             printf("\"%s\" - takes at least one argument\n",argv[0]);
  144.         return -1;
  145.     }
  146.     argc--;
  147.     argv++;
  148.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  149.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  150.             found = 1;
  151.             break;
  152.         }
  153.     }
  154.     if(!found){
  155.         printf("valid subcommands:");
  156.         for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
  157.             printf(" %s",cmdp->name);
  158.         printf("\n");
  159.         return -1;
  160.     }
  161.     if(argc < cmdp->argcmin){
  162.         if(cmdp->argc_errmsg != NULLCHAR)
  163.             printf("Usage: %s\n",cmdp->argc_errmsg);
  164.         return -1;
  165.     }
  166.     if(cmdp->stksize == 0){
  167.         return (*cmdp->func)(argc,argv,p);
  168.     } else {
  169.         /* Make private copy of argv and args */
  170.         pargv = (char **)calloc(argc,sizeof(char *));
  171.         for(i=0;i<argc;i++)
  172.             pargv[i] = strdup(argv[i]);
  173.         pp = newproc(cmdp->name,cmdp->stksize,
  174.          (void (*)())cmdp->func,argc,pargv,p);
  175.         pwait(pp);
  176.         return(0);
  177.     }
  178. }
  179. /* Must be called by all command processes before they exit */
  180. void
  181. freeargs(argc,argv)
  182. int argc;
  183. char *argv[];
  184. {
  185.     char **pargv;
  186.  
  187.     pargv = argv;
  188.     while(argc-- != 0)
  189.         free(*argv++);
  190.     free(pargv);
  191. }
  192.  
  193. /* Subroutine for setting and displaying boolean flags */
  194. int
  195. setbool(var,label,argc,argv)
  196. int *var;
  197. char *label;
  198. int argc;
  199. char *argv[];
  200. {
  201.     struct boolcmd *bc;
  202.  
  203.     if(argc < 2){
  204.         printf("%s: %s\n",label,*var ? "on":"off");
  205.         return 0;
  206.     }
  207.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  208.         if(strcmpi(argv[1],bc->str) == 0){
  209.             *var = bc->val;
  210.             return 0;
  211.         }
  212.     }
  213.     printf("Valid options:");
  214.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  215.         printf(" %s",bc->str);
  216.     printf("\n");
  217.     return 1;
  218. }
  219. /* Subroutine for setting and displaying long variables */
  220. int
  221. setlong(var,label,argc,argv)
  222. long *var;
  223. char *label;
  224. int argc;
  225. char *argv[];
  226. {
  227.     if(argc < 2)
  228.         printf("%s: %lu\n",label,*var);
  229.     else
  230.         *var = atol(argv[1]);
  231.  
  232.     return 0;
  233. }
  234. /* Subroutine for setting and displaying short variables */
  235. int
  236. setshort(var,label,argc,argv)
  237. unsigned short *var;
  238. char *label;
  239. int argc;
  240. char *argv[];
  241. {
  242.     if(argc < 2)
  243.         printf("%s: %u\n",label,*var);
  244.     else
  245.         *var = atoi(argv[1]);
  246.  
  247.     return 0;
  248. }
  249.